/*************************************************************************
 *                                                                       *
 * This file is part of the DogosFrame distribution.  For full copyright *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 *                                                                       *
 *************************************************************************/

//declaration header
#include "COMMON/pars/InputManager.h"

//COMMON headers
#include "COMMON/pars/MemoryDatabase.h"
#include "COMMON/pars/Parser.h"
#include "COMMON/tbox/PIO.h"

namespace DOGOS
{

InputManager* InputManager::s_instance = 0;

InputDatabase* InputManager::s_input_db (0);

StartupShutdownManager::Handler InputManager::s_finalize_handler(
    0,
    0,
    0,
    InputManager::finalize_callback,
    StartupShutdownManager::priorityInputManager);

/*
 *************************************************************************
 *
 * Basic singleton classes to create, set, and destroy the manager
 * instance.
 *
 *************************************************************************
 */

InputManager*
InputManager::get_manager()
{
    if (!s_instance)
    {
        s_instance = new InputManager;
    }
    return s_instance;
}



void
InputManager::set_manager(
    InputManager* manager)
{
    if (s_instance)
    {
        delete s_instance;
    }

    s_instance = manager;
}



void
InputManager::finalize_callback()
{
    if (s_input_db)
    {
        delete s_input_db;
        s_input_db = 0;
    }

    if (s_instance)
    {
        delete s_instance;
        s_instance = 0;
    }
}

/*
 *************************************************************************
 *
 * The constructor and destructor are protected and call only be called
 * by the singleton class or its subclasses.
 *
 *************************************************************************
 */

InputManager::InputManager()
{}



InputManager::~InputManager()
{}

/*
 *************************************************************************
 *
 * Parse the specified input file and return the new database.
 *
 *************************************************************************
 */

const InputDatabase*
InputManager::parse_input_file(
    const std::string& file_name)
{
    MemoryDatabase* memory_db = new MemoryDatabase (file_name);
    InputDatabase* db = new InputDatabase (memory_db);

    parse_input_file(file_name, db);
    return db;
}

/*
 *************************************************************************
 *
 * Parse the specified input file into the given database.
 *
 *************************************************************************
 */

void
InputManager::parse_input_file(
    const std::string& file_name,
    InputDatabase* db)
{
    FILE* fstream = 0;

    fstream = fopen(file_name.c_str(), "r");

    int worked = (fstream ? 1 : 0);

    if (!worked)
    {
        TBOX_ERROR ("tbox::InputManager: Could not open input file \""
                    << file_name.c_str() << "\"\n");
    }

    /*
     * Parse input file.
     */
    Parser* parser = new Parser();
    const int errors = parser->parse(file_name, fstream, db);
    const int warnings = parser->get_num_of_warnings();

    if (errors > 0)
    {
        TBOX_ERROR (
            "InputManager: Errors = " << errors
            << ", Warnings = " << warnings
            << "\n when parsing input file = "
            << file_name << std::endl);
        db->get_database()->printClassData (PLOG);
        TBOX_ERROR ("InputManager exiting..." << std::endl);
    }
    if (warnings > 0)
    {
        TBOX_ERROR (
            "InputManager: Warnings  = " << warnings
            << "\n when parsing input file = " << file_name << std::endl);
    }

    /*
     * Store the root database in the static s_input_db variable.
     */
    s_input_db = db;

    delete parser;
    if (fstream) fclose(fstream);
}

}
